package com.cea.papyrus.diagram.classdiagram.editpart;

import java.util.List;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.palette.PaletteDrawer;
import org.eclipse.gef.tools.CellEditorLocator;
import org.eclipse.gef.tools.DirectEditManager;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.Dependency;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.Generalization;
import org.eclipse.uml2.uml.TemplateSignature;

import com.cea.papyrus.core.PapyrusMessages;
import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.directedit.ILabelControler;
import com.cea.papyrus.core.directedit.LabelCellEditorLocator;
import com.cea.papyrus.core.directedit.LabelControler;
import com.cea.papyrus.core.directedit.LabelDirectEditManager;
import com.cea.papyrus.core.directedit.PropertyAccessor;
import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editor.mouseoveraction.ActionHandleManager;
import com.cea.papyrus.core.editpart.ContainerWithSemanticEditPart;
import com.cea.papyrus.core.figures.IconFigure;
import com.cea.papyrus.core.figures.TemplateSignatureFigure;
import com.cea.papyrus.core.ui.dialogs.PapyrusMessageDialog;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagram.classdiagram.helper.NodeRedefinableTemplateSignatureHelper;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * This the control of the Class
 * @author Patrick Tessier
 */
public class RedefinableTemplateSignatureEditPart extends ContainerWithSemanticEditPart {

	/** Manager for editing classname. */
	protected DirectEditManager manager;

	/**
	 * Creates a new ClassEditPart.
	 * @param graphNode
	 * @param modelManager
	 */
	public RedefinableTemplateSignatureEditPart(GraphNode graphNode,ModelManager modelManager) {
		super(graphNode,modelManager);
	}

	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.ContainerEditPart#createEditPolicies()
	 */
	@Override
	protected void createEditPolicies(){
		super.createEditPolicies();
		installEditPolicy(DimensionAdaptationClassEditPolicy.DIMENSION_ADAPTATION, new DimensionAdaptationClassEditPolicy());
		
		if(! this.isElementImport()){
			//begin insertion
			//installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, new ContainerHighlightEditPolicy()) ;
			//installEditPolicy(EditPolicy.LAYOUT_ROLE, new ClassLayoutEditPolicy(
			//		(XYLayout) getContentPane().getLayoutManager()));
			//if(getContentPane() != null) {
			//	installEditPolicy(EditPolicy.LAYOUT_ROLE, new LayoutEditPolicy(
			//			(XYLayout) getContentPane().getLayoutManager()));
			//}
			//end insertion
			installActionHandle();
		}
	}

	/**
	 * Install Action handles for this editPart.
	 * Use same toolEntries than in palette
	 */
	protected void installActionHandle() {

		// Install mouse hover
		ActionHandleManager actionMngr = new ActionHandleManager(this);	
		// Create a toolbar of actions.
		PaletteDrawer entries = new PaletteDrawer("creation tool");

		try{
			entries.add(PapyrusPlugin.creationToolFactory.getConnectionCreationToolEntry(
					PapyrusMessages.AddAssociationCommand_Label
					, PapyrusMessages.AddAssociationCommand_Description
					, Association.class
					, null));
			entries.add(PapyrusPlugin.creationToolFactory.getConnectionCreationToolEntry(
					PapyrusMessages.AddGeneralizationCommand_Label
					, PapyrusMessages.AddGeneralizationCommand_Description
					, Generalization.class
					, null));
			entries.add(PapyrusPlugin.creationToolFactory.getConnectionCreationToolEntry(
					PapyrusMessages.AddDependencyCommand_Label
					, PapyrusMessages.AddDependencyCommand_Description
					, Dependency.class
					, null));
			entries.add(PapyrusPlugin.creationToolFactory.getConnectionCreationToolEntry(
					PapyrusMessages.AddTemplateSignatureCommand_Label
					, PapyrusMessages.AddTemplateSignatureCommand_Description
					, TemplateSignature.class
					, null));
		}
		catch (Exception e) {
			PapyrusMessageDialog.display(e.getMessage(), e);
		}
		actionMngr.addTool(entries, PositionConstants.EAST, false, 5);

	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#createFigure()
	 */
	@Override
	protected IFigure createFigure() {

		// Try to get figure from ContainerWithSemanticEditPart
		IFigure fig = super.createFigure();

		if (fig != null) {
			return fig;
		}

		// else
		return new TemplateSignatureFigure();				
	}

	/* (non-Javadoc)
	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getContentPane()
	 */
	@Override
	public IFigure getContentPane() {
		if (getFigure() instanceof TemplateSignatureFigure) {
			return ((TemplateSignatureFigure) getFigure()).getContentPane();

		} else {
			// Figure is a shape
			return getFigure();
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.gef.editparts.AbstractEditPart#createChild(java.lang.Object)
	 */
	@Override
	protected EditPart createChild(Object model) {
		if( model instanceof GraphNode) {
			EditPart part = null;
			if( ! this.isElementImport()){
				//first graph Node= container of attributes
				if( ((GraphNode)model) == ((GraphNode)getGraphNode().getContained().get(0)) ) {
					part = new TemplateParameterListEditPart((GraphNode)model,modelManager);
				} else {
					throw new RuntimeException("unknown model list");
				}

				part.setModel(model);
				return part;
			}
		}
		return super.createChild(model);
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#getUmlElement()
	 */
	@Override
	public org.eclipse.uml2.uml.RedefinableTemplateSignature getUmlElement() {
		Element e=((Uml1SemanticModelBridge)getGraphNode().getSemanticModel()).getElement();

		// case of element import
		if(e instanceof ElementImport){
			return (org.eclipse.uml2.uml.RedefinableTemplateSignature)((ElementImport) e).getImportedElement();
		}
		// this is a simple Class
		return (org.eclipse.uml2.uml.RedefinableTemplateSignature)e;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.gef.editparts.AbstractEditPart#refreshVisuals()
	 */
	@Override
	protected void refreshVisuals() {
		Debug.debug(this, "refreshvisuals", channel);

		Dimension size = getGraphNode().getSize();
		Point p = getGraphNode().getPosition();
		Rectangle r = new Rectangle(p ,size);
		IFigure fig = getFigure();
		
		// if fig is a stereotype figure
		if (!(fig instanceof TemplateSignatureFigure)) {
//			IconFigure icf= (IconFigure)getFigure();
//			icf.setName("template signature");
		} else {
			// Retrieve current class and figure
			org.eclipse.uml2.uml.RedefinableTemplateSignature currentTemplateSignature = (org.eclipse.uml2.uml.RedefinableTemplateSignature) getUmlElement();
			com.cea.papyrus.umlutils.Element currentElement = new com.cea.papyrus.umlutils.Element(getUmlElement());

			TemplateSignatureFigure f = (TemplateSignatureFigure) fig; //get Class figure
			f.setBackgroundColor(ColorConstants.white);
			
			
		}


		((GraphicalEditPart) getParent()).setLayoutConstraint(
				this,
				fig,
				r);

	}

	/**
	 * Returns the Name Label of this edit part
	 * @return Label
	 */
	protected Label getNameLabel() {
		IFigure fig = getFigure();

		if (fig instanceof IconFigure) {
			return (Label) fig;
		} else if (fig instanceof TemplateSignatureFigure) {
			return ((TemplateSignatureFigure) fig).getNameLabel();
		} else {
			Debug.error(this, "RedefinedTemplateSignatureEditPart::getTextFigure() : Unknown Figure type.", channel);
			return null;
		}
	}

	/**
	 * Init the label direct edit manager.
	 * This method should be called when a Direct Edit request is performed.
	 */
	protected void initLabelEditManager() {
		if(manager==null) {
			// locator for the cell editor (on the name label)
			CellEditorLocator locator = new LabelCellEditorLocator(getNameLabel());

			// defining how properties are modified in the model
			PropertyAccessor accessor = new PropertyAccessor() {
				public String getPropertyName() {
					return "Name";
				}

				public String getValue() {
					if(isElementImport()){
						return getElementImport().getAlias();
					}
//					return getUmlElement().getName();
					return "template signature" ;
				}
				public void setValue(String value) {
					if(isElementImport()){
						getElementImport().setAlias(value);
					}
					//else{getUmlElement().setName(value);}  
				}
			};
			// defines the controler: link between model and view
			ILabelControler labelControler = new LabelControler(getNameLabel(), accessor);

			// creates the editing manager.
			manager = new LabelDirectEditManager(this, locator, labelControler);
		}
	}


	/**
	 * the direct edit mechanism requires the edit part to handle the direct edit
	 * request.
	 * @param req the request that called the direct edit.
	 */
	public void performDirectEdit(Request req) {
		initLabelEditManager();
		manager.show();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.gef.editparts.AbstractEditPart#performRequest(org.eclipse.gef.Request)
	 */
	@Override
	public void performRequest(Request request){
		if (RequestConstants.REQ_DIRECT_EDIT.equals(request.getType())) {
			performDirectEdit(request);
		}
	}
	
	
	@Override
	public void notifyChanged(Notification notification){
		super.notifyChanged(notification) ;
		List childrenEditParts = this.getChildren() ;
		if (childrenEditParts.get(0) instanceof TemplateParameterListEditPart)
			((TemplateParameterListEditPart)childrenEditParts.get(0)).notifyChanged(notification) ;
	}
	
	/**
	 * this method calculate the good position of a port by taking account of his parent.
	 * 
	 * @param point the position of the current port ins absolute coordinate
	 * 
	 * @return the new position of the port.
	 */
	public Point inRunnerOfClass(Point point){
		Dimension templateSignatureNodeDimension = getGraphNode().getSize();
		//apply good position , the defaut is the same point
		NodeRedefinableTemplateSignatureHelper np= new NodeRedefinableTemplateSignatureHelper();
		return np.inRunner((GraphNode)getGraphNode().getSemanticParent(), point, templateSignatureNodeDimension);
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getDragTracker(org.eclipse.gef.Request)
	 */
	@Override
	public DragTracker getDragTracker(Request request) {
		return new RedefinableTemplateSignatureTracker(this);
	}
}
